package vip.kqsy.cloud.blog.server.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import vip.kqsy.cloud.blog.constant.em.BlogInteractiveTypeEm;
import vip.kqsy.cloud.blog.server.mapper.BlogInfoMapper;
import vip.kqsy.cloud.blog.server.pojo.dto.BlogInfoAddDTO;
import vip.kqsy.cloud.blog.server.pojo.dto.BlogInfoUpdateDTO;
import vip.kqsy.cloud.blog.server.pojo.dto.ListBlogInfoDTO;
import vip.kqsy.cloud.blog.server.pojo.dto.PageBlogInfoDTO;
import vip.kqsy.cloud.blog.server.pojo.entity.BlogComment;
import vip.kqsy.cloud.blog.server.pojo.entity.BlogInfo;
import vip.kqsy.cloud.blog.server.pojo.entity.BlogInteractive;
import vip.kqsy.cloud.blog.server.pojo.vo.*;
import vip.kqsy.cloud.blog.server.service.BlogCommentService;
import vip.kqsy.cloud.blog.server.service.BlogInfoService;
import vip.kqsy.cloud.blog.server.service.BlogInteractiveService;
import vip.kqsy.cloud.core.security.user.KqsyUserContext;
import vip.kqsy.cloud.core.web.res.ResPage;
import vip.kqsy.cloud.user.api.SysUserApi;
import vip.kqsy.cloud.user.api.dto.SysUserDTO;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 博客表 服务实现类
 * </p>
 *
 * @author cenjunjie
 * @since 2023-05-03
 */
@Service
@RequiredArgsConstructor
public class BlogInfoServiceImpl extends ServiceImpl<BlogInfoMapper, BlogInfo> implements BlogInfoService {

    private final BlogInteractiveService blogInteractiveService;
    private final SysUserApi sysUserApi;
    private final BlogCommentService blogCommentService;

    @Override
    public ResPage<PageBlogInfoVO> page(PageBlogInfoDTO dto) {
        PageHelper.startPage(dto);
        List<BlogInfo> list = lambdaQuery()
                .like(StringUtils.isNotEmpty(dto.getTitle()), BlogInfo::getTitle, dto.getTitle())
                .orderByDesc(BlogInfo::getCreateTime)
                .list();

        ResPage<BlogInfo> of = ResPage.of(list);
        return of.convertListType(t -> {
            PageBlogInfoVO vo = BeanUtil.toBean(t, PageBlogInfoVO.class);
            Long viewCount = blogInteractiveService.lambdaQuery()
                    .eq(BlogInteractive::getBlogId, t.getId())
                    .eq(BlogInteractive::getType, BlogInteractiveTypeEm.VIEW.getCode())
                    .count();

            Long collectCount = blogInteractiveService.lambdaQuery()
                    .eq(BlogInteractive::getBlogId, t.getId())
                    .eq(BlogInteractive::getType, BlogInteractiveTypeEm.COLLECT.getCode())
                    .count();

            Long likeCount = blogInteractiveService.lambdaQuery()
                    .eq(BlogInteractive::getBlogId, t.getId())
                    .eq(BlogInteractive::getType, BlogInteractiveTypeEm.LIKE.getCode())
                    .count();

            vo.setViewCount(viewCount.intValue());
            vo.setCollectCount(collectCount.intValue());
            vo.setLikeCount(likeCount.intValue());
            return vo;
        });
    }

    @Override
    public void add(BlogInfoAddDTO dto) {
        BlogInfo blogInfo = BeanUtil.toBean(dto, BlogInfo.class);
        blogInfo.setCreateTime(LocalDateTime.now());
        blogInfo.setAuthor(KqsyUserContext.getUser().getId());
        save(blogInfo);
    }

    @Override
    public void update(BlogInfoUpdateDTO dto) {
        BlogInfo blogInfo = BeanUtil.toBean(dto, BlogInfo.class);
        blogInfo.setUpdateTime(LocalDateTime.now());
        updateById(blogInfo);
    }

    @Override
    public BlogInfoDetailVO detail(Long id) {
        BlogInfo blogInfo = getById(id);
        return BeanUtil.toBean(blogInfo, BlogInfoDetailVO.class);
    }

    @Override
    public ResPage<ListBlogInfoVO> list(ListBlogInfoDTO dto) {
        PageHelper.startPage(dto);
        List<ListBlogInfoVO> list = baseMapper.list(dto);
        return ResPage.of(list);
    }

    @Override
    public BlogInfoViewVO view(Long id, Long userId) {
        BlogInfo blogInfo = getById(id);
        BlogInfoViewVO vo = BeanUtil.toBean(blogInfo, BlogInfoViewVO.class);
        SysUserDTO data = sysUserApi.findById(blogInfo.getAuthor()).getData();
        vo.setNickname(data.getNickname());
        vo.setAvatar(data.getAvatar());

        List<BlogInteractive> list = blogInteractiveService.lambdaQuery()
                .eq(BlogInteractive::getBlogId, id)
                .list();

        Map<Integer, List<BlogInteractive>> typeMap = list.stream().collect(Collectors.groupingBy(BlogInteractive::getType));
        vo.setViewCount(typeMap.getOrDefault(BlogInteractiveTypeEm.VIEW.getCode(), Collections.emptyList()).size());
        vo.setLikeCount(typeMap.getOrDefault(BlogInteractiveTypeEm.LIKE.getCode(), Collections.emptyList()).size());

        long count = typeMap.getOrDefault(BlogInteractiveTypeEm.LIKE.getCode(), Collections.emptyList())
                .stream().filter(item -> item.getUserId().equals(userId)).count();
        vo.setIsLiked(count > 0);

        long collectCount = typeMap.getOrDefault(BlogInteractiveTypeEm.COLLECT.getCode(), Collections.emptyList())
                .stream().filter(item -> item.getUserId().equals(userId)).count();
        vo.setIsCollected(collectCount > 0);

        Long cmmCount = blogCommentService.lambdaQuery()
                .eq(BlogComment::getBlogId, id)
                .count();
        vo.setCommentCount(cmmCount.intValue());

        // 点赞
        long viewCount = typeMap.getOrDefault(BlogInteractiveTypeEm.VIEW.getCode(), Collections.emptyList())
                .stream().filter(item -> item.getUserId().equals(userId)).count();
        if (viewCount == 0) {
            BlogInteractive blogInteractive = new BlogInteractive();
            blogInteractive.setBlogId(id);
            blogInteractive.setType(BlogInteractiveTypeEm.VIEW.getCode());
            blogInteractive.setUserId(userId);
            blogInteractive.setCreateTime(LocalDateTime.now());
            blogInteractiveService.save(blogInteractive);
        }
        return vo;
    }

    @Override
    public List<ArchiveVO> archive() {
        return baseMapper.archive();
    }

    @Override
    public List<ListInteractiveBlogVO> listInteractive(Integer type, Long userId) {
        return baseMapper.listInteractive(type, userId);
    }
}
